package com.lj.sys.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.lj.common.exception.CommonException;
import com.lj.common.utils.CheckUtils;
import com.lj.mp.standard.StandardServiceImpl;
import com.lj.mp.utils.PageQueryUtils;
import com.lj.sys.constant.SysConstant;
import com.lj.sys.entity.SysRole;
import com.lj.sys.entity.SysUser;
import com.lj.sys.mapper.SysUserMapper;
import com.lj.sys.param.SysUserChangePasswordParam;
import com.lj.sys.param.SysUserPageParam;
import com.lj.sys.param.SysUserSaveParam;
import com.lj.sys.param.SysUserUpdateParam;
import com.lj.sys.result.DataScopeResult;
import com.lj.sys.result.SysRoleInfoResult;
import com.lj.sys.result.SysUserInfoResult;
import com.lj.sys.service.SysRoleService;
import com.lj.sys.service.SysUserRoleService;
import com.lj.sys.service.SysUserService;
import com.lj.sys.utils.SysUserUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 系统用户 服务实现类
 * </p>
 *
 * @author lj
 * @since 2024-08-09
 */
@Service
public class SysUserServiceImpl extends StandardServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private SysUserRoleService sysUserRoleService;

    @Override
    public IPage<SysUserInfoResult> page(SysUserPageParam param) {
        DataScopeResult dataScope = SysUserUtils.getDataScope();
        param.setDataScopeIdList(dataScope.getUserIdList());
        return baseMapper.querySysUser(PageQueryUtils.getPage(param), param);
    }

    @Override
    public SysUserInfoResult info(Long id) {
        SysUserInfoResult sysUserInfoResult;
        if (SysConstant.SUPER_ADMIN_ID.equals(id)) {
            // 超级管理员querySysUser不会被查询到
            sysUserInfoResult = SysUserInfoResult.of(getById(id));
        } else {
            sysUserInfoResult = baseMapper.querySysUser(id);
        }
        List<SysRole> sysRoleList = sysRoleService.getSysRoleByUserId(id);
        sysUserInfoResult.setRoleInfoList(sysRoleList.stream().map(SysRoleInfoResult::of).toList());
        return sysUserInfoResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysUserSaveParam param) {
        if (param == null) {
            throw new CommonException("新增用户信息不能为空");
        }
        SysUser entity = param.toEntity();
        // 密码加密
        entity.setPassword(SaSecureUtil.sha256(param.getPassword()));
        this.save(entity);
        sysUserRoleService.refresh(entity.getId(), param.getRoleIdList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysUserUpdateParam param) {
        if (param == null) {
            throw new CommonException("更新用户信息不能为空");
        }
        SysUser entity = param.toEntity();
        this.updateById(entity);
        sysUserRoleService.refresh(entity.getId(), param.getRoleIdList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        if (CollUtil.contains(ids, SysConstant.SUPER_ADMIN_ID)) {
            // 超级管理员无法被删除
            throw new CommonException("超级管理员无法删除!");
        }
        for (Long id : ids) {
            sysUserRoleService.refresh(id, Collections.emptySet());
        }
        this.removeBatchByIds(ids);
    }

    @Override
    public void changePassword(SysUserChangePasswordParam param) {
        CheckUtils.ifCondition(StrUtil.equals(param.getNewPassword(), param.getOldPassword()), "新的密码不能与旧密码一致!");
        Long userId = StpUtil.getLoginIdAsLong();
        SysUser sysUser = this.getById(userId);
        CheckUtils.ifNull(sysUser, "无法修改您的密码?请联系管理员!");
        CheckUtils.ifCondition(!StrUtil.equals(sysUser.getPassword(), SaSecureUtil.sha256(param.getOldPassword())),
                "旧密码不正确, 请稍后重试!");
        SysUser update = new SysUser();
        update.setId(sysUser.getId());
        update.setPassword(SaSecureUtil.sha256(param.getNewPassword()));
        this.updateById(update);
    }
}
